A complex computer program can contain millions of lines of code. To manage this complexity, many programmers have adopted object-oriented programming techniques. Object-oriented programming splits a computer program into modules called objects. Each object performs specific functions and interacts with other objects in a pre-defined way. Conventionally, programmers use a definition language to create a specification for an object. This definition language specification defines how the object interacts with other objects. With reference to this definition language specification, programmers then use a programming language to actually write code for the object.
FIG. 1 shows several principles of object-oriented programming with reference to an object 100 that interacts in pre-defined ways with a client 140 (which can also be an object).
The object 100 encapsulates data 110, which indicates the current state of the object 100. The object 100 exposes member functions 120, 122, and 124 that provide access to data 110 or provide some other defined function. To access the data 110, the client 140 of the object 100 goes through a member function. In FIG. 1, the member functions 120, 122, 124 perform related services for the client 140, and are grouped into an interface 126. In some object-oriented programming models, an object can expose multiple interfaces. For example, FIG. 1 also includes an interface 130 (shown without member functions for simplicity).
A particular member function might take arguments as input and/or produce arguments as output. An argument can be, for example, a number, a character, a string of characters, a user-defined data structure, or a pointer. To interact with an object exposing a member function, a client gives arguments of the correct type and in the correct order. The object processes the data for the input arguments according to the member function, and then returns output arguments of the correct type in the correct order. A definition language specification for the object 100 defines how the object 100 and client 140 interact, for example, what arguments to exchange, what order to exchange them, etc. The client 140 and the object 100 interact per the definition language specification, after a programmer has written programming language code to implement the client 140 and the object 100 according to the definition language specification.
Definition languages have evolved to precisely specify information about interfaces, the member functions of interfaces, and the objects that expose interfaces. A definition language for interfaces is commonly termed an interface definition language [“IDL”]. Historically, interface definition languages have sometimes been termed object definition languages or object description languages.
FIGS. 2a and 2b show a source code listing of an IDL file 200 for an object CTest that exposes the interfaces ITest and ITest2. The IDL portion 210 indicates that ITest has methods Grade and Score, and indicates data types for the input and output arguments of Grade and Score. The IDL portion 230 defines ITest2, which includes the methods Display and Hours as well as methods to retrieve and set a value for the property StudentID. The IDL portion 250 describes an object CTest that exposes the ITest and ITest2. This IDL file shows the complexity and intricacy of specifying interfaces with IDL. For more information about the IDL used in IDL file 200, see Kraig Brockschmidt, Inside OLE, second edition, “Chapter 3, Type Information,” Microsoft Press (1995) or Al Major, COM IDL & Interface Design, Wrox Press (1999).
Conventionally, an IDL defines interfaces and objects, while a programming language is used to implement the interfaces for an object according to the IDL specification for the object. IDLs have developed separately from programming languages, follow different rules, and use different tools.
FIG. 3 illustrates separate treatment of IDL and programming language code in a “build process” for creating a binary file 380. In FIG. 3, an IDL file 300 includes an IDL specification for an object and the interfaces of the object. An IDL compiler 310 converts the IDL file 300 to output code such as a type library file 320 describing information types for the interfaces. The IDL compiler 310 also produces a header file 330 for consumption by the C++ compiler 350.
A C++ source code file 340 includes statements in the programming language C++. In this example, the C++ file 340 is for implementing a class that exposes the interfaces defined in the IDL file 300. The C++ compiler 350 converts the C++ file 340 to the output code 360. The C++ compiler uses the header file 330 when converting the C++ source code to the output code 360. The type library is packaged in a RC file 324, from which a resource compiler 326 produces a RES file 328 that is passed to the linker 370. The linker 370 packages the RES file 328 together with the output code 360 and any other appropriate resources into a binary file 380 such as an executable or dynamic link library.
Separate treatment of IDL and programming language code has several disadvantages.
First, when an IDL compiler converts IDL to output code, the IDL compiler strips most IDL information. This stripped IDL information is unavailable to a programming language compiler subsequently receiving the output code, which prevents the programming language compiler from fully utilizing combined knowledge of IDL and programming language code.
Second, separately handling IDL and programming language code complicates programming by requiring separate files and more code from a programmer, and by using different rules and tools.
Third, inconsistencies between IDL files and programming language files can create bugs when a project is being built. Worse yet, run time inconsistencies between programming language code and corresponding IDL can cause a program to inexplicably crash.
Microsoft Corporation's Visual C++ 5.0 and 6.0 provide development tools that somewhat simplify separate treatment of IDL. In Visual C++ 6.0, a “ClassWizard” development tool allows a programmer to add features to an object by manipulating a high level representation of the object. When a programmer adds a feature, IDL is automatically generated and added to a separate IDL file. For more information about development tools that facilitate separate treatment of IDL code and C++ code, see Sphar et al., Learn Microsoft Visual C++ 6.0 Now, Microsoft Press (1998) or Horton, Beginning Visual C++ 6, Wrox Press Ltd. (1998).
These development tools still involve an IDL compiler that converts IDL to output code, stripping most IDL information in the process. A programming language compiler that later handles the output code cannot utilize this lost information. Moreover, although these development tools simplify the separate handling of IDL and programming language code in many respects, they still expose the programmer to separate programming language and IDL files.
Other programming tools recognize selected, limited forms of IDL information in programming language source code. These programming tools typically process the IDL information, pass it through to an output file as IDL metadata, and then discard the IDL information. These tools do not derive any semantic meaning from the IDL information.
For example, Microsoft Corporation's Visual J++ allows placement of IDL attributes of selected, limited types in comments in Java source code. A pre-processor strips away the comments, but preserves the IDL attributes. Later, a compiler passes the IDL information through to an output file as IDL metadata. The compiler does not derive semantic meaning from the IDL information, and fails to fully utilize combined knowledge of IDL and programming language code.